﻿//Copyright (c) Microsoft Corporation. All rights reserved.

using Microsoft.Ted.Wacel.TestConsole.Properties;
using Microsoft.Ted.Wacel;
using System;
using System.Threading.Tasks;

namespace Microsoft.Ted.Wacel.TestConsole
{
    public class TableStorageQueueTester
    {
        public static void EnqueueTest()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", Settings.Default.StorageConnectionString);
            queue.Clear();
            queue.Enqueue("This is a test");
            VisualTester.AreEqual(1, queue.Length);
        }
        public static void DequeueTest()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", Settings.Default.StorageConnectionString);
            queue.Clear();
            queue.Enqueue("This is a test");
            var text = queue.Dequeue();
            VisualTester.AreEqual("This is a test", text);
        }
        public static void QueueCount()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", Settings.Default.StorageConnectionString);
            queue.Clear();
            queue.Enqueue("This is a test");
            queue.Enqueue("This is a test");
            queue.Enqueue("This is a test");
            VisualTester.AreEqual(3, queue.Length);
        }
        public static void EnqueueDequeue5()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", Settings.Default.StorageConnectionString);
            queue.Clear();
            string baseStrig = "Test Base";
            for (int i = 0; i < 5; i++)
                queue.Enqueue(baseStrig + i.ToString());
            for (int i = 0; i < 5; i++)
                VisualTester.AreEqual(baseStrig + i.ToString(), queue.Dequeue());
            VisualTester.AreEqual(0, queue.Length);
        }
        public static void DequeEmptyQueue()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", Settings.Default.StorageConnectionString);
            queue.Clear();
            try
            {
                queue.Dequeue();
                VisualTester.Assert(false);
            }
            catch (InvalidOperationException)
            {
                VisualTester.Assert(true);
            }
            catch (Exception exp)
            {
                VisualTester.Assert(false, exp.Message);
            }
        }
        public static void QueueLengthConstraint()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", 3, Settings.Default.StorageConnectionString);
            queue.Clear();
            queue.Enqueue("A");
            queue.Enqueue("B");
            queue.Enqueue("C");
            try
            {
                queue.Enqueue("D");
                VisualTester.Assert(false);
            }
            catch (InvalidOperationException)
            {
                VisualTester.Assert(true);
            }
            catch (Exception exp)
            {
                VisualTester.Assert(false, exp.Message);
            }
        }
        public static void SafeLoop()
        {
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", 3, Settings.Default.StorageConnectionString);
            queue.Clear();
            for (int i = 0; i < 30; i++)
            {
                queue.Enqueue("A");
                VisualTester.AreEqual(1, queue.Length);
                queue.Dequeue();
                VisualTester.AreEqual(0, queue.Length);
            }
        }
        /// <summary>
        /// This is a complete test case for testing a queue with a single item. 
        /// The queue should function correctly: an item can be correctly enqueued
        /// and dequeued, with correct queue length maintained. But only one item
        /// is allowed.
        /// </summary>
        public static void OneItemQueueOperations()
        {
            //Initialize queue
            TableStorage.Queue<string> queue = new TableStorage.Queue<string>("myqueue", 1, Settings.Default.StorageConnectionString);
            queue.Clear();

            //Enqueue one item
            queue.Enqueue("A");
            VisualTester.AreEqual(1, queue.Length);

            //Enqueue a second item. This is expected to fail.
            try
            {
                queue.Enqueue("B");
                VisualTester.Assert(false);
            }
            catch (InvalidOperationException)
            {
                VisualTester.Assert(true);
            }
            catch (Exception exp)
            {
                VisualTester.Assert(false, exp.Message);
            }

            //Dequeue the item
            var str = queue.Dequeue();
            VisualTester.AreEqual("A", str);
            VisualTester.AreEqual(0, queue.Length);
        }

        /// <summary>
        /// This test simulates concurrent access to a queue, with multiple threads
        /// enqueuing items and then dequeuing items from a single queue. Note the
        /// strict order is not guaranteed in this case.
        /// </summary>
        public static void ParallelEnqueueDequeue()
        {
            int count = 20;
            TableStorage.Queue<int> queue = new TableStorage.Queue<int>("myqueue", count, Settings.Default.StorageConnectionString);
            queue.Clear();

            Parallel.For(0, count, (i) => { queue.Enqueue(i); });
            VisualTester.AreEqual(count, queue.Length);

            Parallel.For(0, count, (i) => { queue.Dequeue(); });
            VisualTester.AreEqual(0, queue.Length);
        }
    }
}
